
import java.io.BufferedReader;
import java.io.EOFException;
import java.io.File;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;

public class SubstitutionMatrix {

	BufferedReader reader;
	File sourceFile;
	List<List<Integer>> matrix;
	String[] xMap;
	List<String> yMap;

	Map<String, Integer> xStrMapping = null;
	Map<String, Integer> yStrMapping = null;
	int[][] valueMatrix = null;

	public SubstitutionMatrix() {
	}

	public void setFile(File file) throws IOException {
		sourceFile = file;
		reader = new BufferedReader(new FileReader(sourceFile));
		init();
	}

	protected void init() throws IOException {
		String line;

		matrix = new LinkedList<List<Integer>>();
		yMap = new LinkedList<String>();
		xStrMapping = null;
		yStrMapping = null;
		valueMatrix = null;

		line = reader.readLine();
		for (int count = 0; line != null; count++) {
			if (count == 0) {
				initXMap(line);
			} else {
				appendToMatrix(count, line);
			}
			count++;
			line = reader.readLine();
		}
		reader.close();
	}

	private void appendToMatrix(int count, String line) {
		String[] pcs = line.split("\\s+");
		yMap.add(pcs[0]);

		List<Integer> matrixLine = new ArrayList<Integer>(pcs.length - 1);
		matrix.add(matrixLine);
		for (int i = 1; i < pcs.length; i++) {
			matrixLine.add(new Integer(pcs[i]));
		}
	}

	private void initXMap(String line) {
		String[] pcs = line.split("\\s+");
		xMap = new String[pcs.length - 1];
		for (int i = 1; i < pcs.length; i++) {
			xMap[i - 1] = pcs[i];
		}
	}

	public Map<String, Integer> getXStrMapping() {
		if (xStrMapping == null) {
			xStrMapping = new HashMap<String, Integer>(xMap.length);
			for (int i = 0; i < xMap.length; i++) {
				xStrMapping.put(xMap[i], new Integer(i));
			}
		}
		return xStrMapping;
	}

	public Map<String, Integer> getYStrMapping() {
		if (yStrMapping == null) {
			yStrMapping = new HashMap<String, Integer>(yMap.size());
			for (int i = 0; i < yMap.size(); i++) {
				yStrMapping.put(yMap.get(i), new Integer(i));
			}
		}
		return yStrMapping;
	}

	public int[][] getValueMatrix() {
		if (valueMatrix == null) {
			valueMatrix = new int[xMap.length][yMap.size()];
			for (int x = 0; x < xMap.length; x++) {
				List<Integer> matrixLine = matrix.get(x);
				for (int y = 0; y < yMap.size(); y++) {
					valueMatrix[x][y] = matrixLine.get(y).intValue();
				}
			}
		}
		return valueMatrix;
	}

}
